﻿// ******************* RACK ****************************

var Rack = function(dc) {
	var self = this;
	this.dc = dc;
	this.last_left = 0;
	this.last_top = 0;
	this.max_z = 10;
	this.grid_width = 100;
	this.grid_height = 120;
	this.grid = {};
	this.edit_mode = false;
	
	this.Load(dc);
	
	this.Append = function (item) {
		var self = this;
		if (item.dc_id != this.dc.id) return;
		var title = '<b>' + item.name + '</b><br />'
		+ '<b>Vendor</b>: ' + item.vendor + '<br />'
		+ '<b>Units</b>: ' + item.units + '<br />'
		+ '<b>Notes</b>: ' + item.notes + '<br />'
		+ '<b>Responsible</b>: ' + item.responsible;
		var units = {};
		console.log(item.units);
		for (var i = parseInt(item.units); i > 0; i--) {
			console.log(i);
			units[i] = true;
		}
		//console.log('units: ' + units);
		//console.log('used: ' + item.used_units);
		if (item.used_units) {
			var used_units = item.used_units.split(',');
			for (var i = 0; i < used_units.length; i++) {
				var unit = used_units[i];
				if (unit.indexOf('-') > -1) {
					var pair = unit.split('-');
					var first = parseInt(pair[0]);
					var last = parseInt(pair[1]);
					if (last < first) {
						first = parseInt(pair[1]);
						last = parseInt(pair[2]);
					}
					for (var ii = first; ii <= last; ii++) {
						if (units[parseInt(ii)]) delete units[parseInt(ii)];
					}
				} else {
					if (units[parseInt(unit)]) delete units[parseInt(unit)];
				}
			}
		}
		var cnt = 0;
		for (var key in units) {
			if (units.hasOwnProperty(key)) cnt++;
		}
		var used_units_cnt = parseInt(item.units) - cnt;
		var free_units_cnt = cnt;
		var info = '<b>Used</b>: ' + used_units_cnt + '<br /><b>Free</b>: ' + free_units_cnt;
		var li = $('<li class="ui-state-default ui-corner-all rack"><div class="header">' + item.name + '</div><div class="info">' + info + '</div></li>')
		.data('data', item)
		.appendTo('#racks_list')
		.tooltip(title).draggable({
			grid: [self.grid_width, self.grid_height],
			disabled: true,
			addClasses: false,
			start: function(event, ui) {
				/*ui.helper.bind("click.prevent",
                function(event) { event.preventDefault(); });*/
				this.dragged = true;
				$(this).css('zIndex', self.max_z);
				self.max_z++;
			},
			stop: function(event, ui) {
				var self = this;
				$(self).data('new_left', $(self).offset().left - $('#racks_list').offset().left);
				$(self).data('new_top', $(self).offset().top - $('#racks_list').offset().top + 8);
				console.log('position: left = ' + $(this).position().left + ', top = ' + $(this).position().top);
				console.log('offset: left = ' + $(this).offset().left + ', top = ' + $(this).offset().top);
				setTimeout(function(){ self.dragged = false; }, 300);
			}
		});
		li.click(function () {
			if (!this.dragged) {
				var server = new Server(item);
				server.ItemsChanged = function(count) {
					used_units_cnt += count;
					free_units_cnt -= count;
					info = '<b>Used</b>: ' + used_units_cnt + '<br /><b>Free</b>: ' + free_units_cnt;
					li.children('.info').empty().append(info);
				}
			}
		})
		item = this.CheckGrid(item);
		if ($('#dc_container').dialog('isOpen') === true) {
			li.css({position: 'absolute'}).offset({left: item.left + $('#racks_list').offset().left - 17, top: item.top + $('#racks_list').offset().top - 8});
		} else {
			li.css({position: 'absolute'}).offset({left: item.left, top: item.top});
		}
		/*console.log(self.last_left + ' + ' + self.last_top);
		if ($('#dc_container').dialog('isOpen') === true) {
			li.css({position: 'absolute'}).offset({left: self.last_left + $('#racks_list').offset().left - 17, top: self.last_top + $('#racks_list').offset().top - 8});
		} else {
			li.css({position: 'absolute'}).offset({left: self.last_left, top: self.last_top});
		}
		self.last_left += self.grid_width;
		if (self.last_left + self.grid_width > li.parent().actual('width')) {
			self.last_left = 0;
			self.last_top += self.grid_height;
		}*/
		//$('#dc_container').dialog('option', 'height', self.last_top + 200);
		//self.last_top += 120;
		return li;
	};
	
	this.EnterEditMode = function() {
		this.edit_mode = true;
		$('#dc_container').dialog('option', 'resizable', true);
		$('#dc_container').bind('dialogresizestop', function() {
			$(this).data('resized_width', $(this).width());
			$(this).data('resized_height', $(this).height());
			console.log('container width: ' + $(this).width());
			console.log('container height: ' + $(this).height());
		});
		$('#entrance').draggable('enable').css('cursor', 'move');
		$('#racks_list li').draggable('enable').each(function(index, item) {
			item = $(item);
			item.unbind('click').children('.header').css('cursor', 'move');
			//.addClass('moveable');
			self.AppendEditButtons(item);
		});
		var btn = $('#racks_add_icon');
		if (btn.length == 0) {
			btn = $("<a href='#' style='float:right; padding-top:10px;padding-bottom:10px;'></a>")
			.button({ icons: { primary: "ui-icon-plus" }, text: false }).attr('id', 'racks_add_icon')
			.insertAfter($('#racks_edit_mode_icon'));
		} else btn.unbind('click').show();
		btn.click(function() {
			self.Add();
		});
		$('#racks_edit_mode_icon').button('option', 'icons', { primary: "ui-icon-check" }).unbind('click').click(function() {
			self.LeaveEditMode();
		});
	};
	
	this.LeaveEditMode = function() {
		if (!this.edit_mode) return;
		this.edit_mode = false;
		$('#dc_container').dialog('option', 'resizable', false);
		$('#dc_container').unbind('dialogresizestop');
		if ($('#dc_container').data('resized_width') || $('#dc_container').data('resized_width')) {
			var width = $('#dc_container').data('resized_width') || self.dc.width;
			var height = $('#dc_container').data('resized_height') || self.dc.height;
			console.log('resize: ' + width + 'x' + height);
			var call = new DcCall();
			call.Resize(self.dc, width, height, function() {
				self.dc.width = width;
				self.dc.height = height;
			});
		}
		$('#racks_add_icon').unbind('click').hide();
		$('#racks_edit_mode_icon').button('option', 'icons', { primary: "ui-icon-pencil" }).unbind('click').click(function() {
			self.EnterEditMode();
		});
		$('#racks_list li a').unbind('click').remove();
		// hack here: remove class
		$('#entrance').draggable('disable').removeClass('ui-state-disabled').css('cursor', '');
		$('#racks_list li').draggable('disable').removeClass('ui-state-disabled').each(function (index, item) {
			$(item).click(function () { var server = new Server($(item).data('data')); }).children('.header').css('cursor', '');
		}).each(function(index, item) {
			var left = $(item).data('new_left');
			var top = $(item).data('new_top');
			if (typeof left != 'undefined' || typeof top != 'undefined') {
				var data = $(item).data('data');
				if (typeof left == 'undefined') left = data.left;
				if (typeof top == 'undefined') top = data.top;
				console.log('move ' + data.id + ' to ' + top + 'x' + data.left);
				var call = new RackCall();
				call.Move(data.id, top, left, function() {
					data.top = top;
					data.left = left;
					$(item).data('data', data).removeData('new_left').removeData('new_top');
				});
			}
		});
		var entrance_left = $('#entrance').offset().left - $('#dc_container').offset().left;
		if (entrance_left != self.dc.entrance_left) {
			var call = new DcCall();
			call.MoveEntrance(self.dc.id, self.dc.entrance_top, entrance_left, function() {
				self.dc.entrance_left = entrance_left;
				if (self.DcChanged) self.DcChanged(self.dc);
			});
		}
	};
	
	this.AppendEditButtons = function(item) {
		if (!item) return;
		var edit = $("<a href='#' style='padding-top:10px;padding-bottom:10px;position:absolute;'></a>").button({ icons: { primary: "ui-icon-pencil" }, text: false }).appendTo(item).click(function () { self.Edit(item); });
		edit.offset({left: edit.parent().offset().left + 50, top: edit.parent().offset().top + 70});
		var add = $("<a href='#' style='padding-top:10px;padding-bottom:10px;position:absolute;'></a>").button({ icons: { primary: "ui-icon-close" }, text: false }).appendTo(item).click(function () { self.Remove(item); });
		add.offset({left: edit.parent().offset().left + 10, top: edit.parent().offset().top + 70});
	};

};

Rack.prototype.Remove = function(item) {
	var call = new RackCall();
	call.Remove($(item).data('data'), function() {
		$(item).remove();
	});
	return false;
};

Rack.prototype.Edit = function(item) {
	var self = this;
	var form = new RackForm('edit');
	form.Empty();
	form.Load($(item).data('data'));
	form.Show(function(data) {
		if (data.dc_id != self.dc.id) {
			item.remove();
		} else {
			item.children('.header').empty().append(data.name);
			item.children('.info').empty().append(data.notes);
			var title = '<b>' + data.name + '</b><br />'
			+ '<b>Vendor</b>: ' + data.vendor + '<br />'
			+ '<b>Units</b>: ' + data.units + '<br />'
			+ '<b>Notes</b>: ' + data.notes + '<br />'
			+ '<b>Responsible</b>: ' + data.responsible;
			item.tooltip(title);
			item.data('data', data);
		}
	});
	return false;
}

Rack.prototype.Add = function() {
	var self = this;
	var form = new RackForm('add');
	form.Empty();
	form.dc(self.dc.id);
	form.Show(function(data) {
		console.log('append ' + data);
		self.AppendEditButtons(self.Append(data).unbind('click'));
	});
	return false;
}

Rack.prototype.BuildGrid = function(width, height) {
	for (var i = 0; i < height; i += this.grid_height) {
		for (var ii = 0; ii < width; ii += this.grid_width) {
			this.grid[i + 'x' + ii] = 0; // top x left
		}
	}
	//console.log(this.grid);
};

Rack.prototype.CheckGrid = function(item) {
	if (this.grid[item.top + 'x' + item.left]) { // ячейка занята
		//console.log('cell is busy');
		for (var cell in this.grid) {
			//console.log('check cell ' + cell);
			if (!this.grid[cell]) {
				//console.log('cell is empty');
				var pair = cell.split('x');
				var top = parseInt(pair[0]);
				var left = parseInt(pair[1]);
				item.left = left;
				item.top = top;
				this.grid[cell] = item;
				break;
			}
		}
	} else {
		this.grid[item.top + 'x' + item.left] = item;
	}
	return item;
};

Rack.prototype.Load = function(dc) {
	var self = this;
	if (dc) self.dc = dc;
	var call = new RackCall();
	$('#dc_container').attr('title', self.dc.name).empty().append("<ol id='racks_list' class='main_list'></ol>");
	//var width = Math.floor($(document).width() / 300) * 300;
	var width = self.dc.width ? self.dc.width : 1500;
	//var height = self.last_top + 200;
	var height = self.dc.height ? self.dc.height : 900;
	self.BuildGrid(width, height);
	call.Load(self.dc.id, function(item) {
		self.Append(item);
	}, function() {
		$('#dc_container').dialog({ title: self.dc.name, modal: true, "width": width, "height": height, resizable: false, close: function() { 
			self.LeaveEditMode(); 
			$('#entrance').remove(); 
		}, resize: function() {
			$('#entrance').offset({top: $('#dc_container').offset().top + $('#dc_container').height() - 7});
		} }).data('old_height', height).data('old_width', width);

		// add buttons
		var btn = $('#racks_edit_mode_icon');
		if (btn.length == 0) {
			btn = $("<a href='#' style='float:right; padding-top:10px;padding-bottom:10px;margin-right:15px;'></a>")
			.button({ icons: { primary: "ui-icon-pencil" }, text: false }).attr('id', 'racks_edit_mode_icon')
			.insertBefore($('#dc_container').prev().children('a').first());
		} else btn.unbind('click');
		btn.click(function (e) {
			e.preventDefault();
			self.EnterEditMode();
		});
		self.AppendEntrance();
	});
}

Rack.prototype.AppendEntrance = function() {
	var self = this;
	var container = $('#dc_container').parent();
	container.css('overflow', 'visible');
	//$('#dc_container').css('overflow', 'auto');
	var ent = $('<div id="entrance" class="ui-state-default ui-corner-all" style="position:absolute; width:auto;">ENTRANCE</div>').appendTo(container).css('zIndex', 5000);
	ent.offset({left: parseInt(self.dc.entrance_left) + parseInt($('#dc_container').offset().left), top: $('#dc_container').offset().top + $('#dc_container').height() - 7});
	console.log(parseInt(self.dc.entrance_left));
	ent.draggable({
		disabled: true,
		containment: 'parent',
		//snapMode: 'outer',
		axis: 'x',
		addClasses: false,
		start: function(event, ui) {
			/*ui.helper.bind("click.prevent",
			function(event) { event.preventDefault(); });*/
			this.dragged = true;
			$(this).css('zIndex', self.max_z);
			self.max_z++;
		},
		stop: function(event, ui) {
			var self = this;
			$(self).data('new_left', $(self).offset().left - $('#racks_list').offset().left);
			$(self).data('new_top', $(self).offset().top - $('#racks_list').offset().top + 8);
			console.log('position: left = ' + $(this).position().left + ', top = ' + $(this).position().top);
			console.log('offset: left = ' + $(this).offset().left + ', top = ' + $(this).offset().top);
			setTimeout(function(){ self.dragged = false; }, 300);
		}
	});
}
// ******************* Rack Full *******************************
var RackFull = function() {
	var self = this;
	this.Load();
};

RackFull.prototype.Load = function() {
	var self = this;
	var call = new RackCall();
	$('.rack_td_edit').unbind('click');
	$('.rack_td_remove').unbind('click');
	$('#tab-racks tbody').empty();
	call.Load(0, function(item) {
		self.AppendRow(item);
	});
};

RackFull.prototype.AppendRow = function(item) {
	var self = this;
	var tr = $('<tr><td>' + item.dc + '</td><td>' + item.name + '</td><td>' + item.vendor + '</td><td>' + item.units + '</td><td>' + item.notes + '</td><td>' + item.responsible + '</td><td class="rack_td_edit">&nbsp;</td><td class="rack_td_remove">&nbsp;</td></tr>').appendTo('#tab-racks tbody').data('data', item);
	$("<a href='#'></a>")
	.button({ icons: { primary: "ui-icon-pencil" }, text: false })
	.appendTo(tr.children('.rack_td_edit')).click(function() {
		self.Edit($(this).parent().parent());
		return false;
	});
	$("<a href='#'></a>")
	.button({ icons: { primary: "ui-icon-close" }, text: false })
	.appendTo(tr.children('.rack_td_remove')).click(function() {
		self.Remove($(this).parent().parent());
		return false;
	});
}

RackFull.prototype.UpdateRow = function(row, item) {
	var self = this;
	row.data('data', item).children().first().text(item.dc).next().text(item.name).next().text(item.vendor).next().text(item.units).next().text(item.notes).next().text(item.responsible);
}

RackFull.prototype.Remove = function(row) {
	var call = new RackCall();
	call.Remove(row.data('data'), function() {
		row.remove();
	});
	return false;
}

RackFull.prototype.Add = function() {
	var self = this;
	var form = new RackForm('add');
	form.Empty();
	form.Show(function(data) {
		self.AppendRow(data);
	});
	return false;
}

RackFull.prototype.Edit = function(row) {
	var self = this;
	var form = new RackForm('edit');
	form.Empty();
	form.Load(row.data('data'));
	form.Show(function(data) {
		self.UpdateRow(row, data);
	});
	return false;
}

// ********************** Rack form ****************************
var RackForm = function(mode) {
	this.mode = mode;
	this._vendor = new Vendor($('#form_rack_vendor'));
	this._vendor.Load();
	this._dc = new DcSelect($('#form_rack_dc'));
	this._dc.Load();
};
RackForm.prototype.id = function(value) {
	if (typeof value == 'undefined') return $('#form_rack_id').val();
	else $('#form_rack_id').val(value);
}
RackForm.prototype.dc = function(value) {
	if (typeof value == 'undefined') return this._dc.SelectedValue();
	else this._dc.Select(value);
}
RackForm.prototype.dcName = function() {
	return this._dc.SelectedName();
}
RackForm.prototype.name = function(value) {
	if (typeof value == 'undefined') return $('#form_rack_name').val();
	else $('#form_rack_name').val(value);
}
RackForm.prototype.vendor = function(value) {
	if (typeof value == 'undefined') return this._vendor.SelectedValue();
	else this._vendor.Select(value);
}
RackForm.prototype.vendorName = function() {
	return this._vendor.SelectedName();
}
RackForm.prototype.units = function(value) {
	if (typeof value == 'undefined') return $('#form_rack_units').val();
	else $('#form_rack_units').val(value);
}
RackForm.prototype.notes = function(value) {
	if (typeof value == 'undefined') return $('#form_rack_notes').val();
	else $('#form_rack_notes').val(value);
}
RackForm.prototype.responsible = function(value) {
	if (typeof value == 'undefined') return $('#form_rack_responsible').val();
	else $('#form_rack_responsible').val(value);
}
RackForm.prototype.Empty = function() {
	this.id('');
	this.dc(0);
	this.name('');
	this.vendor(0);
	this.units(0);
	this.notes('');
	this.responsible('');
}
RackForm.prototype.Load = function(data) {
	this.id(data.id);
	this.dc(data.dc_id);
	this.name(data.name);
	this.vendor(data.vendor_id);
	this.units(data.units);
	this.notes(data.notes);
	this.responsible(data.responsible);
}
RackForm.prototype.Show = function(callback) {
	var self = this;
	var title = (this.mode == 'add') ? 'Add new rack' : 'Edit rack';
	$('#rack_edit_form').dialog({ title: title, modal: true, width: 'auto', height: 'auto', buttons: {
		'Save': function () {
			var vendor = self.vendor();
			if (vendor == 0) {
				Confirm('Are you sure to add vendor ' + self.vendorName() + '?', function() { self._vendor.AddValue(save); });
			} else save();
			function save() {
				var opts = {
					dc_id: self.dc(),
					dc: self.dcName(),
					name: self.name(),
					vendor_id: self.vendor(),
					vendor: self.vendorName(),
					units: self.units(),
					notes: self.notes(),
					responsible: self.responsible()
				};
				if (self.mode == 'edit') opts.id = self.id();
				var call = new RackCall();
				call.Save(self.mode, opts, function(data) {
					if (callback) callback(data);
					$('#rack_edit_form').dialog('close');
				});
			}
		},
		'Cancel': function () {
			$(this).dialog('close');
		}
	}});
}
// ********************* Rack Call ************************
var RackCall = function() {
}

RackCall.prototype.Load = function(dc_id, callback, finish_callback) {
	var self = this;
	var sfx = dc_id ? 'dc_id=' + dc_id : 'mode=full';
	$.getJSON('/call.aspx?source=rack&' + sfx, function(data) {
		var cnt = data.length;
		if (cnt == 0 && finish_callback) finish_callback();
		else {
			$.each(data, function(index, item) {
				cnt--;
				if (callback) callback(item);
				if (cnt == 0) {
					if (finish_callback) finish_callback();
				}
			});
		}
	});
};

RackCall.prototype.GetList = function(callback) {
	$.getJSON('/call.aspx?source=rack&mode=list', function (data) {
		if (callback) callback(data);
	});
}
RackCall.prototype.Save = function(mode, data, callback) {
	data.mode = mode;
	data.source = 'rack';
	$.getJSON('/call.aspx', data, function (result) {
		if (result.result == 'RESULT_OK') {
			var item = {
				name: data.name,
				vendor_id: data.vendor_id,
				vendor: data.vendor,
				dc_id: data.dc_id,
				dc: data.dc,
				units: data.units,
				notes: data.notes,
				responsible: data.responsible
			};
			item.id = (mode == 'add') ? result.id : data.id;
			if (callback) callback(item);
		} else {
			Warning('Error during saving of the rack', result.result);
		}
	});
}
RackCall.prototype.Remove = function(data, callback) {
	Confirm('Are you sure to remove rack ' + data.name + ' and all servers within it?', function() {
		$.getJSON('/call.aspx', { source: 'rack', mode: 'remove', id: data.id }, function (result) {
			if (result.result == 'RESULT_OK') {
				if (callback) callback();
			} else {
				Warning('Error during removing of ' + data.name, result.result);
			}
		});
	});
}

RackCall.prototype.Move = function(id, top, left, callback) {
	$.getJSON('/call.aspx', {source: 'rack', mode: 'move', 'id': id, 'left': left, 'top': top}, function(result) {
		if (result.result == 'RESULT_OK') {
			if (callback) callback();
		} else {
			Warning('Error during moving of rack ' + id, result.result);
		}
	});
}

RackCall.prototype.LockUnit = function(id, unit, callback) {
	$.getJSON('/call.aspx', {source: 'rack', mode: 'lock', 'id': id, 'unit': unit}, function(result) {
		if (result.result == 'RESULT_OK') {
			if (callback) callback();
		} else {
			Warning('Error during locking unit ' + unit + ' in rack ' + id, result.result);
		}
	});
}

RackCall.prototype.UnlockUnit = function(id, unit, callback) {
	$.getJSON('/call.aspx', {source: 'rack', mode: 'unlock', 'id': id, 'unit': unit}, function(result) {
		if (result.result == 'RESULT_OK') {
			if (callback) callback();
		} else {
			Warning('Error during unlocking unit ' + unit + ' in rack ' + id, result.result);
		}
	});
}
// *************************** Rack select **************************
var RackSelect = function(control) {
	var self = this;
	this.control = control;
	this.racks = [];
	this.selected = 0;
	this.filter = 0;
};

RackSelect.prototype.SelectedName = function() {
	return this.control.next().val();
};

RackSelect.prototype.SelectedValue = function() {
	for (var i in this.racks) {
		if (this.racks[i].name == this.SelectedName()) return this.racks[i].id;
	}
	return 0;
};

RackSelect.prototype.Load = function(selected) {
	var self = this;
	if (selected) self.selected = selected;
	var call = new RackCall();
	call.GetList(function(data) {
		self.racks = data;
		self.control.combobox('destroy').empty();
		self.control.append('<option value="0">--</option>');
		$.each(data, function (index, item) {
			if (!self.filter || (self.filter && self.filter == item.dc_id)) self.control.append('<option value="' + item.id + '">' + item.name + '</option>');
		});
		self.control.combobox({strict: true});
		self.Select(self.selected);
	});
};

RackSelect.prototype.Filter = function(dc_id) {
	var self = this;
	this.filter = dc_id;
	self.control.combobox('destroy').empty();
	self.control.append('<option value="0">--</option>');
	for (i in this.racks) {
		if (this.racks[i].dc_id == dc_id) {
			self.control.append('<option value="' + this.racks[i].id + '">' + this.racks[i].name + '</option>');
		}
	}
	self.control.combobox({strict: true});
	self.Select(self.selected);
}

RackSelect.prototype.Select = function(value) {
	var self = this;
	self.selected = value;
	if (self.racks.length > 0) {
		if (!value) {
			self.control.val(0);
			self.control.next().val('--');
		} else if (isNaN(parseInt(value))) {
			for (var i in self.racks) {
				var item = self.racks[i];
				if (item.name == value) {
					self.control.val(item.id);
					self.control.next().val(item.name);
					break;
				}
			}
		} else {
			for (var i in self.racks) {
				var item = self.racks[i];
				if (item.id == value) {
					self.control.val(item.id);
					self.control.next().val(item.name);
					break;
				}
			}
		}
	}
};
